/* 
 * DrawMgr.cs
 * Part of Gamadus Engine. Visit www.gamadus.de.vu!
 * 
 * [DONE] Commenting finished.
 */

using System;
using System.Collections.Generic;
using System.Drawing;

using OpenTK;
using OpenTK.OpenGL;
using OpenTK.OpenGL.Enums;
using OpenTK.Fonts;
using OpenTK.Math;
using OpenTK.Input;
using OpenTK.Platform;


namespace Gamadus.Engine
{
	/// <summary>
	/// The Draw Manager. It holds some variables needed for drawing
	/// and some static primitive drawing methods.
	/// </summary>
	public class DrawMgr : SingletonManager<DrawMgr>
	{
		/// <summary>
		/// The current drawing Font.
		/// </summary>
		public Font CurrentFont
		{
			get
			{
				return currentFont;
			}
			set
			{
				//TODO: set font
				currentFont = value;
			}
		}
		private Font currentFont;
		
		
		/// <summary>
		/// The current drawing color.
		/// </summary>
		public Color CurrentColor
		{
			get
			{
				return currentColor;
			}
			set
			{
				GL.Color3(value);
				currentColor = value;
			}
		}
		private Color currentColor;
		
		/// <summary>
		/// If false, the objekt is not in draw event and no drawing actions can be done (except on surfaces)
		/// TODO: implement this
		/// </summary>
		public bool DrawEvent = false;
		
		/// <summary>
		/// Inits the Manager. Call before starting main loop.
		/// </summary>
		public void Init()
		{
			CurrentColor = Color.Black;
		}
		
		#region Drawing Primitives
		
		/// <summary>
		/// Draws a point
		/// [DONE] This function is checked to draw exactly what GM does.
		/// </summary>
		/// <param name="p">The point</param>
		static public void DrawPoint(Point p)
		{
			GL.Begin(BeginMode.Points);
				GL.Vertex2(p.X, p.Y+1);
			GL.End();
		}
		
		/// <summary>
		/// Draws a line
		/// [DONE] This function is checked to draw exactly what GM does.
		/// </summary>
		/// <param name="p1">The beginning of the line</param>
		/// <param name="p2">The end of the line</param>
		static public void DrawLine(Point p1, Point p2)
		{
			GL.Begin(BeginMode.Lines);
				GL.Vertex2(p1.X, p1.Y);
				GL.Vertex2(p2.X, p2.Y);
			GL.End();
		}
		/// <summary>
		/// Draws a rectangle.
		/// [DONE] This function is checked to draw exactly what GM does.
		/// </summary>
		/// <param name="p1">The upper left corner</param>
		/// <param name="p2">The lower right corner</param>
		/// <param name="fill">Whether to fill the rectangle or not</param>
		static public void DrawRectangle(Point p1, Point p2, bool fill)
		{
			if(fill)
			{
				GL.Begin(BeginMode.Quads);
				GL.Vertex2(p1.X, p1.Y); //top left
				GL.Vertex2(p1.X, p2.Y+1); //bottom left
				GL.Vertex2(p2.X+1, p2.Y+1); //bottom right
				GL.Vertex2(p2.X+1, p1.Y); //top right
				GL.End();
			}
			else
			{
				GL.Begin(BeginMode.LineLoop);
				
				GL.Vertex2(p1.X+1, p1.Y); //top left
				GL.Vertex2(p1.X+1, p2.Y); //bottom left
				GL.Vertex2(p2.X+1, p2.Y); //bottom right
				GL.Vertex2(p2.X+1, p1.Y); //top right
				GL.End();
				DrawPoint(new Point(p1.X, p2.Y));
			}
		}
		
		/// <summary>
		/// Draws a circle
		/// TODO: This function is not checked to draw exactly what GM does.
		/// </summary>
		/// <param name="p">The center point</param>
		/// <param name="radius">The radius</param>
		/// <param name="fill">Whether it should be filled or not</param>
		static public void DrawCircle(Point p, int radius, bool fill)
		{
			DrawEllipse(p, radius, radius, fill);
		}
		
		/// <summary>
		/// Draws an ellipse
		/// TODO: This function is not checked to draw exactly what GM does.
		/// </summary>
		/// <param name="p">The center point</param>
		/// <param name="radius1">The first radius</param>
		/// <param name="radius2">The second radius</param>
		/// <param name="fill">Whether it should be filled or not</param>
		static public void DrawEllipse(Point p, int radius1, int radius2, bool fill)
		{
			double vectorY1=p.Y+radius2;
			double vectorX1=p.X;
			double vectorX;
			double vectorY;
			if(fill)
				GL.Begin(BeginMode.Polygon);
			else
				GL.Begin(BeginMode.LineLoop);			
			for(float angle=0.0f;angle<=(2.0f*3.14159);angle+=0.01f)
			{		
				vectorX=p.X+(radius1*(float)Math.Sin((double)angle));
				vectorY=p.Y+(radius2*(float)Math.Cos((double)angle));		
				GL.Vertex2(vectorX1,vectorY1);
				vectorY1=vectorY;
				vectorX1=vectorX;			
			}
			GL.End();
		}
		
		#endregion
	}
}
